Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

467 feature request add dsts support #482

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

handsomejack-42
Copy link
Collaborator

No description provided.

@handsomejack-42 handsomejack-42 linked an issue Apr 15, 2024 that may be closed by this pull request
@handsomejack-42 handsomejack-42 force-pushed the 467-feature-request-add-dsts-support branch 3 times, most recently from 5517451 to 83ca36e Compare April 15, 2024 16:02
@handsomejack-42
Copy link
Collaborator Author

it's still in draft, but I would like some feedback @chlowell, if I'm taking this to the right direction. there's more than enough code already, I think I covered all the cases mentioned in the linked issue.

localhost = "http://localhost"
refresh = "fake_refresh"
token = "fake_token"
)

var tokenScope = []string{"the_scope"}

func fakeClient(tk accesstokens.TokenResponse, credential Credential, options ...Option) (Client, error) {
client, err := New(fakeAuthority, fakeClientID, credential, options...)
func fakeClient(tk accesstokens.TokenResponse, credential Credential, fAuthority string, options ...Option) (Client, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pls undo this name shortnening as it is harder to read the code.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expanded

err = c.Comm.JSONCall(ctx, endpoint, http.Header{}, qv, nil, &resp)
}
return resp, err
}

func (c Client) DSTSInstanceDiscovery(ctx context.Context, authorityInfo Info) (InstanceDiscoveryResponse, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very surprised to see this, was under the impression that dSTS doesn't support instance discovery.

CC @victorm-hernandez

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, instance discovery is not supported.

"tenant can't be common for AAD": {authority: host + uuid1, tenant: "common", expectError: true},
"tenant can't be consumers for AAD": {authority: host + uuid1, tenant: "consumers", expectError: true},
"tenant can't be organizations for AAD": {authority: host + uuid1, tenant: "organizations", expectError: true},
"can't override tenant for ADFS ever": {authority: host + "adfs", tenant: uuid1, expectError: true},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a test for ADFS where tenant is null / empty and where we expect to get back the original authority.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

@handsomejack-42 handsomejack-42 removed the request for review from chlowell May 7, 2024 15:16
The field isn't used anywhere. Removing it simplifies the work on introducing
authority abstraction. We might re-add it once we need it for anything.
…t readability

Previously, the test results were printed as #0 #1 #2, which made it
hard to navigate the failed test cases. Now, the test cases
are annotated by their respective names. The names also make it
more clear what is being unit-tested.
…ONCall

Parsing the url, then setting qv.Encode() manually to u.RawQuery
feel like an overcomplicated approach of creating url for http request.

Use the native constructor, which enforces ctx to be
passed into the request, and do simple sprintf for url + query.
This enables adding the same const for dSTS later in the process.
@handsomejack-42 handsomejack-42 force-pushed the 467-feature-request-add-dsts-support branch from 83ca36e to 35a4182 Compare May 9, 2024 08:33
@handsomejack-42 handsomejack-42 marked this pull request as ready for review May 9, 2024 08:35
@@ -23,7 +23,8 @@ import (

const (
authorizationEndpoint = "https://%v/%v/oauth2/v2.0/authorize"
instanceDiscoveryEndpoint = "https://%v/common/discovery/instance"
aadInstanceDiscoveryEndpoint = "https://%v/common/discovery/instance"
dstsInstanceDiscoveryEndpoint = "https://%v/dstsv2/common/discovery/instance"
Copy link

@victorm-hernandez victorm-hernandez May 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://%v/dstsv2/common/discovery/instance

We need some changes server side from dSTS before implementing this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

authorityType = ADFS
case "dstsv2":
if len(pathParts) != 3 {
return Info{}, errors.New(`dSTS authority must be an https URL such as "https://<authority>/dstsv2/<your tenant>"`)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dSTS doesnt support tenants, the value for the tenant is hard coded everywhere and should always be the same.

Lets change the error to reflect this. The tenant is

7a433bfc-2514-4697-b467-e0933190487f

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hard-coded tenant + added validation

return fmt.Sprintf("https://%s/adfs/.well-known/openid-configuration", authorityInfo.Host), nil
} else if authorityInfo.AuthorityType == authority.DSTS {
resp, err := m.rest.Authority().DSTSInstanceDiscovery(ctx, authorityInfo)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DSTSInstanceDiscovery

Similar to ADFS, you can use a hard coded URL for dSTS. An example of this endpoint on dSTS

https://test-instance1-dsts.dsts.core.azure-test.net/dstsv2/7a433bfc-2514-4697-b467-e0933190487f/.well-known/openid-configuration

IMPORTANT! To connect to this endpoint you need to be on our VPN.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hard-coded the url

host := "https://localhost/"
for _, test := range []struct {

tests := map[string]struct {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tests

Please make sure to run this against real dSTS at least once.

The best way to do this is to create a sample project on the following repository

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this test isn't actually firing any http requests, can you elaborate on what you mean by 'against real dSTS at least once'? I am not aware of any tests which I changed in the context of this PR are actually accessing anything e2e

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean if you want me to manually validate that we can get a token from dSTS using this flow I can do that (I already did that a long time ago, but the set-up we used was deprecated by the recent dSTS crack-down on MS-corp based identities)

I guess that is why you are suggesting to 'build my own test dSTS' in C# and run it locally to test against? because at this point I can't see any easy way of how to call dSTS from SAW (I can hardly compile go there), so the only thing that comes to mind is some ev2 shell extension or something

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend moving this discussion outside of GitHub. Happy to cut a preview release for testing purposes. Agree that we should have some sort of manual validation, at least of some scenarios (client_credentials flow probably. I think user flows are a bit broken right now anyway)

ExtExpiresOn: internalTime.DurationTime{T: time.Now().Add(1 * time.Hour)},
GrantedScopes: accesstokens.Scopes{Slice: tokenScope},
TokenType: "Bearer",
}, cred, "https://fake_authority/dstsv2/fake_tenant")
Copy link

@victorm-hernandez victorm-hernandez May 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fake_tenant

nit: tenant is always fixed on dSTS (7a433bfc-2514-4697-b467-e0933190487f)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

t.Errorf("unexpected access token %s", tk.AccessToken)
}

// fail for another tenant

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tenant

Given that dSTS has a single tenant, there is no need for this test.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe there still is a value in checking that we will fail the execution in case anyone tries to do WithTenant on dSTS flow

case ADFS:
return p, errors.New("ADFS authority doesn't support tenants")
case DSTS:
authority = "https://" + path.Join(p.AuthorityInfo.Host, "dstsv2", ID)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

authority

Since the tenant ID should always be the same for dSTS, the correct behavior is to throw if it is not the expected GUID

7a433bfc-2514-4697-b467-e0933190487f

otherwise build the authority URL.

Copy link
Collaborator Author

@handsomejack-42 handsomejack-42 May 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed to always return an error if it hits this case, there are only three possible cases on WithTenant for dSTS flow that we care about

  1. ID == "" -> returns identical AuthParams
  2. ID == dSTS tenant -> returns identical AuthParams
  3. neither of the above -> should return error

Copy link

@victorm-hernandez victorm-hernandez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🕐

@handsomejack-42 handsomejack-42 force-pushed the 467-feature-request-add-dsts-support branch from 35a4182 to 5ee15d8 Compare May 29, 2024 09:29
@handsomejack-42 handsomejack-42 force-pushed the 467-feature-request-add-dsts-support branch from 5ee15d8 to 99f29ff Compare May 29, 2024 09:30
Copy link

sonarcloud bot commented May 29, 2024

Quality Gate Passed Quality Gate passed

Issues
2 New issues
0 Accepted issues

Measures
0 Security Hotspots
No data about Coverage
0.0% Duplication on New Code

See analysis details on SonarCloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature Request] Add dSTS support
3 participants